/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.beepmystuff;

import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.replay;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.test.ActivityUnitTestCase;

/**
 * Test cases for the home screen activity.
 */
public class HomeScreenActivityTest extends ActivityUnitTestCase<HomeScreenActivity> {
  private static final String SESSION_TOKEN = "a_session_token";
  private static final String PASSWORD = "a_password";
  private static final String NICKNAME = "a_nickname";
  private final TestInjector injector;
  private final BmsLowLevelClient mockBmsLowLevelClient;

  public HomeScreenActivityTest() {
    super(HomeScreenActivity.class);
    injector = new TestInjector();
    mockBmsLowLevelClient = createStrictMock(BmsLowLevelClient.class);  // order matters
  }

  @Override
  protected void setUp() throws Exception {
    super.setUp();
    Injector.configureForTest(injector);
  }

  @Override
  protected void tearDown() throws Exception {
    Injector.resetForTest();
    super.tearDown();
  }

  /**
   * Ensures the activity launched and ran ok.
   */
  public void testActivityTestCaseSetUpProperly() throws Exception {
    FakePreferences preferences = createDefaultFakePreferences();
    injector.setPreferences(preferences)
        .setSessionStorage(preferences)
        .setBmsHttpClient(new DummyBmsHttpClient())
        .setBmsLowLevelClient(mockBmsLowLevelClient);
    replay(mockBmsLowLevelClient);

    startActivity(getIntent(), null, null);
    assertNotNull("activity should be launched successfully", getActivity());
    getActivity().onResume();
    assertNull(getStartedActivityIntent());

    getActivity().waitUntilServiceFullyBound();
  }

  public void testLaunchesLoginActivityOnNoNickname() throws Exception {
    FakePreferences preferences = createDefaultFakePreferences();
    preferences.setNickname("");
    injector.setPreferences(preferences)
        .setSessionStorage(preferences)
        .setBmsHttpClient(new DummyBmsHttpClient())
        .setBmsLowLevelClient(mockBmsLowLevelClient);
    replay(mockBmsLowLevelClient);

    startActivity(getIntent(), null, null);
    getActivity().onResume();
    Intent startedIntent = getStartedActivityIntent();
    assertNotNull("should have started an intent", startedIntent);
    assertEquals(LoginActivity.class.getName(), startedIntent.getComponent().getClassName());

    getActivity().waitUntilServiceFullyBound();
  }

  public void testLaunchesLoginActivityOnNoPassword() throws Exception {
    FakePreferences preferences = createDefaultFakePreferences();
    preferences.setPassword("");
    injector.setPreferences(preferences)
        .setSessionStorage(preferences)
        .setBmsHttpClient(new DummyBmsHttpClient())
        .setBmsLowLevelClient(mockBmsLowLevelClient);
    replay(mockBmsLowLevelClient);

    startActivity(getIntent(), null, null);
    getActivity().onResume();
    Intent startedIntent = getStartedActivityIntent();
    assertNotNull("should have started an intent", startedIntent);
    assertEquals(LoginActivity.class.getName(), startedIntent.getComponent().getClassName());

    getActivity().waitUntilServiceFullyBound();
  }

  // TODO: this test seems bogus.  Why is the home screen activity checking
  // the session token?
  public void testLaunchesLoginActivityOnNoSessionToken() throws Exception {
    FakePreferences preferences = createDefaultFakePreferences();
    preferences.setSessionToken("");
    injector.setPreferences(preferences)
        .setSessionStorage(preferences)
        .setBmsHttpClient(new DummyBmsHttpClient())
        .setBmsLowLevelClient(mockBmsLowLevelClient);
    replay(mockBmsLowLevelClient);

    startActivity(getIntent(), null, null);
    getActivity().onResume();
    Intent startedIntent = getStartedActivityIntent();
    assertNotNull("should have started an intent", startedIntent);
    assertEquals(LoginActivity.class.getName(), startedIntent.getComponent().getClassName());

    getActivity().waitUntilServiceFullyBound();
  }

  /**
   * Creates some FakePreferences, with defaults to just get the BeepMyStuff
   * screen up and running.
   */
  private FakePreferences createDefaultFakePreferences() {
    FakePreferences fakePreferences = new FakePreferences();
    PackageInfo pi;
    try {
      PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
      pi = pm.getPackageInfo("com.google.beepmystuff", 0);
    } catch (NameNotFoundException e) {
      throw new AssertionError("Could not get our own package info: " + e);
    }
    fakePreferences.setLastRunVersion(Integer.toString(pi.versionCode));
    fakePreferences.setNickname(NICKNAME);
    fakePreferences.setPassword(PASSWORD);
    fakePreferences.setSessionToken(SESSION_TOKEN);
    return fakePreferences;
  }

  /**
   * Create an Intent to pass to the activity.
   */
  private Intent getIntent() {
    Intent testIntent = new Intent();
    testIntent.addCategory(Intent.CATEGORY_TEST);
    return testIntent;
  }
}
